package com.huanke.iot.gateway.io.impl;

import com.alibaba.fastjson.JSON;
import com.huanke.iot.base.constant.DeviceConstant;
import com.huanke.iot.base.dao.device.DeviceMapper;
import com.huanke.iot.base.dao.device.ability.DeviceAbilityMapper;
import com.huanke.iot.base.dao.device.alarm.DeviceAlarmDataMapper;
import com.huanke.iot.base.dao.device.data.DeviceControlMapper;
import com.huanke.iot.base.dao.device.data.DeviceSensorDataMapper;
import com.huanke.iot.base.po.device.DevicePo;
import com.huanke.iot.base.po.device.alarm.DeviceAlarmDataPo;
import com.huanke.iot.base.po.device.data.DeviceControlData;
import com.huanke.iot.base.po.device.data.DeviceSensorPo;
import com.huanke.iot.gateway.io.AbstractHandler;
import com.huanke.iot.gateway.mqttlistener.MqttService;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Repository
@Slf4j
public class ControlHandler extends AbstractHandler {

    private static final List<String> sensor_datas = Arrays.asList("HSG2", "HSG1","111", "120", "130", "131", "140", "141", "150", "160", "110", "170", "180", "142", "143");

    //需特殊处理的map  （型号，（类型，处理方法类型））
    public final static Map<Integer,Map> specialModelMap = new HashMap() {{
        put(403, new HashMap() {{
            put("S401", 1);
            put("S402", 1);
            put("S403", 1);
            put("F39", 1);
        }});
        put(414, new HashMap() {{
            put("130", 2);
            put("140", 3);
        }});
        put(420, new HashMap() {{
            put("S411", 4);
            put("S412", 4);
            put("S413", 4);
            put("S414", 4);
        }});
    }};

    //需要特殊处理负数的指令
    private static final List<String> minus_sensor = Arrays.asList("F39", "130", "140", "142", "143", "144");


    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DeviceControlMapper deviceControlMapper;
    @Autowired
    private DeviceSensorDataMapper deviceSensorDataMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceAlarmDataMapper deviceAlarmMapper;
    @Autowired
    private DeviceAbilityMapper deviceAbilityMapper;
    @Autowired
    private MqttService mqttService;

    @Data
    public static class FuncItemMessage{
        private String type;
        private String value;
        private String childid;
    }

    @Data
    public static class FuncListMessage{
        private Integer msg_id;
        private String msg_type;
        private List<ControlHandler.FuncItemMessage> datas;
    }

    @Override
    protected String getTopicType() {
        return "control";
    }

    @Override
    public void doHandler(String topic, byte[] payloads) {

        String datas = new String(payloads);
        ControlHandler.FuncListMessage funcListMessage = JSON.parseObject(datas,ControlHandler.FuncListMessage.class);
        funcListMessage.getDatas().forEach(funcItemMessage -> {
            if (StringUtils.isEmpty(funcItemMessage.getType())){
                return;
            }
            Integer deviceId = getDeviceIdFromTopic(topic);
            String childId = funcItemMessage.getChildid();

            if (deviceId == 600219 && ("1".equals(childId) || "2".equals(childId))){
                if ("2DD2".equals(funcItemMessage.getType()) || "2DD3".equals(funcItemMessage.getType())){
                    int value = Integer.valueOf(funcItemMessage.getValue()) * 10;
                    funcItemMessage.setValue(Integer.toString(value));
                }
            }

            //获取设备用于判断是否需要特殊处理
            DevicePo device;
            if (childId != null && !StringUtils.equals("0",childId)){
                //若上报子设备信息，则修改deviceId为子设备
                DevicePo childDevice = deviceMapper.getChildDevice(deviceId, childId);
                if(childDevice != null){
                    device = childDevice;
                    deviceId = childDevice.getId();
                }else{
                    return;
                }
            }else {
                device = deviceMapper.selectById(deviceId);
            }

            //判断查出的设备是否为空
            if(device != null){
                //判断如果型号和指令需要特殊处理
                if (specialModelMap.containsKey(device.getModelId())){
                    Map specialModelTypes = specialModelMap.get(device.getModelId());
                    if(specialModelTypes.containsKey(funcItemMessage.getType())){
                        //保留两位小数格式化
                        DecimalFormat decimalFormat=new DecimalFormat(".00");
                        //获取处理类型
                        int handleType = (int)specialModelTypes.get(funcItemMessage.getType());

                        if (handleType == 1){               //32位浮点型处理
                            Integer value_32 = Integer.valueOf(funcItemMessage.getValue());
                            float value_float = Float.intBitsToFloat(value_32);
                            funcItemMessage.setValue(Float.toString(value_float));
                        }else if (handleType == 2){         //公式：ROUND((返回值*125/65536-6),2)
                            Integer originalValue = Integer.valueOf(funcItemMessage.getValue());
                            double calculationValue = originalValue*125/65536-6;
                            String value = decimalFormat.format(calculationValue);
                            funcItemMessage.setValue(value);
                        }else if (handleType == 3){         //公式：ROUND((175.72*返回值/65536-46.85),2)
                            Integer originalValue = Integer.valueOf(funcItemMessage.getValue());
                            double calculationValue = 175.72*originalValue/65536-46.85;
                            String value = decimalFormat.format(calculationValue);
                            funcItemMessage.setValue(value);
                        }else if (handleType == 4){         //32位long高低位互换处理
                            Integer value_32 = Integer.valueOf(funcItemMessage.getValue());
                            int value_low = value_32>>>16;
                            int value_high = value_32<<16;
                            funcItemMessage.setValue(Float.toString(value_high+value_low));
                        }

                    }

                }
            }


            String funcId = funcItemMessage.getType(); //获取上报功能项，进一步处理
            //对负数指令特殊处理
            if (minus_sensor.contains(funcId)){
                double value = Double.parseDouble(funcItemMessage.getValue());
                if (value > 64000){
                    funcItemMessage.setValue(String.valueOf((byte) value));
                }
            }

            List<String> deviceAbilityFuncIdList = deviceAbilityMapper.selectbyConfigType(2); //查所有设备报警/故障项
            if(deviceAbilityFuncIdList.contains(funcId)){
                //如果该功能项是设备告警/故障
                DeviceAlarmDataPo  deviceAlarmDataPo = new DeviceAlarmDataPo();
                deviceAlarmDataPo.setDeviceId(deviceId);
                deviceAlarmDataPo.setCode(funcId);
                deviceAlarmDataPo.setValue(funcItemMessage.getValue());
                deviceAlarmDataPo.setAlarmTime(new Date());
                deviceAlarmMapper.insert(deviceAlarmDataPo);
                return;
            }
            ////如果该功能项是设备普通功能项
            DeviceControlData deviceControlData = new DeviceControlData();
            deviceControlData.setFuncId(funcId);
            deviceControlData.setFuncValue(funcItemMessage.getValue());
            deviceControlData.setCreateTime(System.currentTimeMillis());
            deviceControlData.setDeviceId(deviceId);
            try {
                //上报指令为210且值不为0,重置为开机状态
                if(deviceControlData.getFuncId().equals("210")){
                    if(!deviceControlData.getFuncValue().equals(0)) {
                        //this.powerCheckService.resetPowerStatus(deviceControlData.getDeviceId());
                    }else{
                        //log.info("deviceId = {}, send close machine ", deviceControlData.getDeviceId());
                        DevicePo updatePo = new DevicePo();
                        updatePo.setId(deviceId);
                        updatePo.setPowerStatus(DeviceConstant.POWER_STATUS_YES);
                        deviceMapper.updateById(updatePo);
                    }
                }
                if(sensor_datas.contains(deviceControlData.getFuncId())){
                    //如果是传感器数据，存到sensor_data一份
                    DeviceSensorPo deviceSensorPo = new DeviceSensorPo();
                    //如果是Taiying数据，做特殊处理
                    taiYingDatas(deviceId, payloads, deviceControlData.getFuncId());
                    deviceSensorPo.setSensorType(funcId);
                    String value = funcItemMessage.getValue();
                    if(StringUtils.isEmpty(value)){
                        value = "0";
                    }
                    deviceSensorPo.setSensorValue(value);
                    deviceSensorPo.setCreateTime(System.currentTimeMillis());
                    deviceSensorPo.setDeviceId(deviceId);
                    try {
                        deviceSensorDataMapper.insert(deviceSensorPo);
                        stringRedisTemplate.opsForHash().put("sensor2." + deviceId, funcId, String.valueOf(funcItemMessage.getValue()));
                        //stringRedisTemplate.expire("sensor2." + deviceId,30, TimeUnit.MINUTES);
                    }catch (Exception e){
                        log.error("",e);
                    }
                }
                try {
                    deviceControlMapper.insert(deviceControlData);
                }catch (Exception e){

                }
                //如果上报状态为开关机状态则进行记录
                //如果开关为双指令，特殊处理
                if(StringUtils.equals(funcItemMessage.getType(),"ON")){
                    stringRedisTemplate.opsForHash().put("control2." + deviceId, "OFF", "0");
                }else if (StringUtils.equals(funcItemMessage.getType(),"OFF")){
                    stringRedisTemplate.opsForHash().put("control2." + deviceId, "ON", "0");
                }
                stringRedisTemplate.opsForHash().put("control2." + deviceId, funcId, String.valueOf(funcItemMessage.getValue()));
                //stringRedisTemplate.expire("control2." + deviceId,30, TimeUnit.MINUTES);
            }catch (Exception e){
                log.error("",e);
            }
        });


    }

    /**
     * Taiying数据特殊处理
     * @param deviceId
     * @param payloads
     * 100277 --> 538
     * 100583 --> 556
     */
    public void taiYingDatas( Integer deviceId, byte[] payloads, String funcId){
        if (deviceId == 100277){
            falseDatas("/up2/control/538", payloads);
            if ("120".equals(funcId) || "160".equals(funcId)){
                falseDatas("/up2/control/556", payloads);
            }
        }else if (deviceId == 100583){
            falseDatas("/up2/control/556", payloads);
        }

    }

    public void falseDatas(String topic, byte[] payloads){
        mqttService.sendMessage(topic, new String(payloads), false);
    }

}
